//
//  File.swift
//
//
//  Created by didi on 2022/9/13.
//

import Fluent
import MolecularObjects
import Vapor

public protocol ModelController: Controller {
    associatedtype ApiModel: ObjectModel
    associatedtype DatabaseModel: MolecularDatabaseModel

    static var moduleName: String { get }
    static var modelName: MolecularModelName { get }

    func identifier(_ req: Request) throws -> UUID
    func findBy(_ id: UUID, _ req: Request) async throws -> DatabaseModel
    func getBaseRoutes(_ routers: RoutesBuilder) -> RoutesBuilder
}

public extension ModelController {
    static var moduleName: String { DatabaseModel.From.uniqueKey.lowercased().capitalized }
    static var modelName: MolecularModelName { .init(stringLiteral: String(DatabaseModel.uniqueKey.dropLast(1))) }

    func identifier(_ req: Request) throws -> UUID {
        guard let id = ApiModel.getIdParameter(req) else {
            throw Abort(.badRequest)
        }

        return id
    }

    func findBy(_ id: UUID, _ req: Request) async throws -> DatabaseModel {
        guard let model = try await DatabaseModel.find(id, on: req.db) else {
            throw Abort(.notFound)
        }

        return model
    }

    func getBaseRoutes(_ routers: RoutesBuilder) -> RoutesBuilder {
        routers.grouped(ApiModel.Module.pathKey.pathComponent)
            .grouped(ApiModel.pathKey.pathComponent)
    }
}
